package com.admin.service.impl;

import com.admin.persistence.sys.entity.UserGroup;
import com.admin.persistence.sys.entity.UserUsergroup;
import com.admin.persistence.sys.mapper.PersonUserMapper;
import com.admin.persistence.sys.mapper.UserGroupMapper;
import com.admin.persistence.sys.mapper.UserUsergroupMapper;
import com.admin.service.SysUserGroupService;
import com.admin.service.SysUserService;
import com.admin.service.vo.SysUser;
import com.admin.service.vo.SysUserGroup;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.admin.common.CommonUtils;
import com.admin.common.biz.BizBaseResult;
import com.admin.common.biz.ModelUseStatus;
import com.admin.common.biz.ResultStatus;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Service
public class SysUserGroupServiceImp implements SysUserGroupService {

    @Autowired
    UserGroupMapper userGroupMapper;

    @Autowired
    UserUsergroupMapper userUsergroupMapper;

    @Autowired
    SysUserService sysUserService;

    @Autowired
    PersonUserMapper personUserMapper;

    @Override
    public SysUserGroup createSysUserGroup(SysUserGroup sysUserGroup) {
        UserGroup curUserGroup = sysUserGroup.getUserGroup();
        List<SysUserGroup> sysUserGroupChildrens = sysUserGroup.getChildren();
        UserGroup fatherUserGroup = sysUserGroup.getFartherUserGroup();

        curUserGroup.setId(CommonUtils.createId());
        curUserGroup.setFatherGroupId(fatherUserGroup.getId());
        if (userGroupMapper.insert(curUserGroup) < 1) return null;

        if (!CollectionUtils.isEmpty(sysUserGroupChildrens)) {
            sysUserGroupChildrens.stream().map(cur -> {
                return cur.getUserGroup();
            }).filter(curChildren -> {
                return curChildren != null && !StringUtils.isEmpty(curChildren.getId());
            }).forEach(em -> {
                em.setFatherGroupId(curUserGroup.getId());
                userGroupMapper.updateById(em);
            });
        }

        return sysUserGroup;
    }

    @Override
    public int saveSysUserGroup(SysUserGroup sysUserGroup) {
        UserGroup userGroup = sysUserGroup.getUserGroup();
        if (queryById(userGroup.getId()) == null) {
            userGroup.setId(CommonUtils.createId());
            return userGroupMapper.insert(userGroup);
        } else {
            return userGroupMapper.updateById(userGroup);
        }
    }

    @Override
    public int editionSysUserGroup(SysUserGroup sysUserGroup) {
        return userGroupMapper.updateById(sysUserGroup.getUserGroup());
    }

    @Override
    public int removeSysUserGroup(SysUserGroup sysUserGroup) {
        UserGroup userGroup = sysUserGroup.getUserGroup();
        userGroup.setStatus(ModelUseStatus.REMVOE.value);
        return userGroupMapper.updateById(sysUserGroup.getUserGroup());
    }

    @Override
    public SysUserGroup queryById(String id) {
        UserGroup userGroup = userGroupMapper.selectById(id);
        if (userGroup == null) return null;
        List<SysUserGroup> childrens = queryChildrenByFatherGroup(userGroup.getId(), true).getChildren();
        UserGroup fatherUserGroup = userGroupMapper.selectById(userGroup.getFatherGroupId());
        return new SysUserGroup(userGroup, childrens, fatherUserGroup);
    }

    @Override
    public List<SysUserGroup> queryAll() {
        List<SysUserGroup> results = new ArrayList<>();
        List<UserGroup> userGroups = userGroupMapper.selectList(null);
        if (!CollectionUtils.isEmpty(userGroups)) {
            userGroups.stream().forEach(cur -> {
                List<SysUserGroup> childrens = queryChildrenByFatherGroup(cur.getId(), true).getChildren();
                UserGroup fatherUserGroup = userGroupMapper.selectById(cur.getFatherGroupId());
                results.add(new SysUserGroup(cur, childrens, fatherUserGroup));
            });
        }
        return results;
    }

    @Override
    public SysUserGroup queryChildrenByFatherGroup(String fartherGroupId, boolean isEnd) {
        UserGroup userGroup = userGroupMapper.selectById(fartherGroupId);
        SysUserGroup curRoot = new SysUserGroup(userGroup, null, null);
        catchChildren(curRoot, isEnd);
        return curRoot;
    }

    private void catchChildren(SysUserGroup curRoot, boolean isEnd) {
        Optional.ofNullable(curRoot).ifPresent(root -> {
            UserGroup rootUserGroup = root.getUserGroup();
            List<UserGroup> childrenUserGroups = userGroupMapper.selectList(new QueryWrapper<UserGroup>().eq("FATHER_GROUP_ID",
                    rootUserGroup.getId()));
            List<SysUserGroup> childrenSysUserGroups = new ArrayList<SysUserGroup>();
            if (!CollectionUtils.isEmpty(childrenUserGroups)) {
                childrenUserGroups.stream().forEach(curChildren -> {
                    SysUserGroup sysUserGroup = new SysUserGroup(curChildren, null, null);
                    childrenSysUserGroups.add(sysUserGroup);
                    if (isEnd) {
                        catchChildren(sysUserGroup, isEnd);
                    }
                });
            }
            curRoot.setChildren(childrenSysUserGroups);
            curRoot.setFartherUserGroup(userGroupMapper.selectById(rootUserGroup.getId()));
        });
    }

    @Override
    public SysUserGroup queryFartherByChildren(String childrenId) {
        SysUserGroup sysUserGroup = null;
        UserGroup curChildren = userGroupMapper.selectById(childrenId);
        if (curChildren == null) return null;
        UserGroup father = userGroupMapper.selectById(curChildren.getFatherGroupId());
        sysUserGroup = new SysUserGroup(curChildren, null, father);
        catchChildren(sysUserGroup, true);
        return sysUserGroup;
    }

    private void catchFather(SysUserGroup curChildren) {
        UserGroup userGroup = curChildren.getUserGroup();
        String fatherId = userGroup.getFatherGroupId();
        if (!StringUtils.isEmpty(fatherId)) {
            userGroupMapper.selectById(fatherId);
        }
    }

    @Override
    public List<SysUserGroup> queryByPersonInfo(String personId, List<String> personIds, String name, String emial,
                                                String idCard, String phone, boolean use) {
        List<SysUserGroup> results = new ArrayList<SysUserGroup>();
        List<SysUser> sysUsers = sysUserService.queryListByPersonInfo(personId, personIds, name, emial, idCard, phone, use);
        if (CollectionUtils.isEmpty(sysUsers)) return results;
        List<String> userIds = sysUsers.stream().map(cur -> {
            return cur.getUser().getId();
        }).collect(Collectors.toList());
        Optional.ofNullable(userUsergroupMapper.selectList(new QueryWrapper<UserUsergroup>().in("USER_ID", userIds))).ifPresent(cur -> {
            cur.stream().forEach(em -> {
                results.add(queryById(em.getUserGroupId()));
            });
        });
        return results;
    }

    @Override
    public List<SysUserGroup> queryByUser(String userId) {
        List<SysUserGroup> result = new ArrayList<SysUserGroup>();
        List<UserGroup> curUserGroups = userGroupMapper.queryByUser(userId);
        if (!CollectionUtils.isEmpty(curUserGroups)) {
            curUserGroups.stream().forEach(cur -> {
                SysUserGroup sysUserGroup = new SysUserGroup(cur, null, userGroupMapper.selectById(cur.getFatherGroupId()));
                catchChildren(sysUserGroup, true);
                result.add(sysUserGroup);
            });
        }
        return result;
    }

    @Override
    public List<String> bindUser(List<String> userIds, List<String> userGroupIds) {
        List<String> result = new ArrayList<String>();
        if (!CollectionUtils.isEmpty(userIds) && !CollectionUtils.isEmpty(userGroupIds)) {
            userIds.forEach(userId -> {
                userGroupIds.forEach(userGroupId -> {
                    if (userUsergroupMapper.insert(new UserUsergroup(CommonUtils.createId(), userId, userGroupId)) > 0) {
                        result.add(userGroupId);
                    }
                });
            });
        }
        return result;
    }

    @Override
    public List<String> unbindUser(List<String> userIds) {
        List<String> result = new ArrayList<String>();
        Optional.ofNullable(userIds).ifPresent(cur -> {
            cur.stream().filter((em) -> {
                return !StringUtils.isEmpty(em);
            }).forEach(index -> {
                if (userUsergroupMapper.delete(Wrappers.<UserUsergroup>lambdaQuery().eq(UserUsergroup::getUserId, index)) > 0) {
                    result.add(index);
                }
            });
        });
        return result;
    }

    @Override
    public BizBaseResult canRemove(SysUserGroup sysUserGroup) {
        BizBaseResult bizBaseResult = new BizBaseResult();
        UserGroup userGroup = sysUserGroup.getUserGroup();
        if (!CollectionUtils.isEmpty(userUsergroupMapper.selectList(new QueryWrapper<UserUsergroup>().eq("USER_GROUP_ID",
                userGroup.getId())))) {
            bizBaseResult.setStatus(ResultStatus.FAIL.value);
            bizBaseResult.setResultStr("已挂钩成员");
        }
        return bizBaseResult;
    }

    @Override
    public boolean canUseUserGroupName(String name) {
        return CollectionUtils.isEmpty(userGroupMapper.selectList(new QueryWrapper<UserGroup>().eq("NAME", name)));
    }
}
